package com.codi.api.cat;

import com.dianping.cat.Cat;
import com.dianping.cat.message.Event;
import com.dianping.cat.message.Transaction;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;

/**
 * @author machong
 * @date 2018/05/22
 */
@Aspect
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CatServiceAspect {

    @Around("execution(* com.codi.bus.core.service..*Service.*(..))")
    public Object catService(ProceedingJoinPoint joinPoint) throws Throwable {
        Transaction t = Cat.newTransaction("service", getFullMethodName(joinPoint));
        return catMethod(joinPoint, t);
    }

    @Around("execution(* com.codi.bus.core.dao..*Dao.*(..))")
    public Object catManager(ProceedingJoinPoint joinPoint) throws Throwable {
        Transaction t = Cat.newTransaction("dao", getFullMethodName(joinPoint));
        return catMethod(joinPoint, t);
    }

    private Object catMethod(ProceedingJoinPoint joinPoint, Transaction t) throws Throwable {
        try {
            Object result = joinPoint.proceed();
            t.setStatus(Transaction.SUCCESS);
            return result;
        } catch (Throwable e) {
            catArgs(joinPoint);
            Cat.logError(e);
            t.setStatus(e);
            throw e;
        } finally {
            t.complete();
        }
    }

    private static String getFullMethodName(String className, ProceedingJoinPoint joinPoint) {
        if (className == null) {
            className = joinPoint.getTarget().getClass().getSimpleName();
        }
        String methodName = joinPoint.getSignature().getName();
        return className + "." + methodName;
    }

    private static String getFullMethodName(ProceedingJoinPoint joinPoint) {
        return getFullMethodName(null, joinPoint);
    }

    private void catArgs(ProceedingJoinPoint joinPoint) {
        Object[] getArgs = joinPoint.getArgs();
        if (getArgs != null && getArgs.length > 0) {
            StringBuilder stringBuilder = new StringBuilder();
            for (Object object : getArgs) {
                stringBuilder.append(object);
                stringBuilder.append(",");
            }
            Cat.logEvent("method", "args", Event.SUCCESS,
                StringUtils.substringBeforeLast(stringBuilder.toString(),","));
        }
    }

}
